package com.htfyun.roobofactory.rooboUtils;

// huyuguang@360.cn
// The java FileLock based on fcntl which can not use in multi-thread env.
// Java does not has class base on flock which support multi-thread.
// So use domain socket to implement a cross-process spinlock.

import android.net.LocalServerSocket;

import java.io.IOException;

public class SocketLock {
    private final String mName;
    private LocalServerSocket mServer;

    public SocketLock(String name) {
        mName = name;
    }

    public final synchronized void tryLock() throws IOException {
        if (mServer == null) {
            mServer = new LocalServerSocket(mName);
        } else {
            throw new IllegalStateException("tryLock but has locked");
        }
    }

    public final synchronized boolean timedLock(int ms) {
        long expiredTime = System.currentTimeMillis() + ms;

        while (true) {
            if (System.currentTimeMillis() > expiredTime) {
                return false;
            }
            try {
                try {
                    tryLock();
                    return true;
                } catch (IOException e) {
                    // ignore the exception
                }
                Thread.sleep(10, 0);
            } catch (InterruptedException e) {
                continue;
            }
        }
    }

    public final synchronized void lock() {
        while (true) {
            try {
                try {
                    tryLock();
                    return;
                } catch (IOException e) {
                    // ignore the exception
                }
                Thread.sleep(10, 0);
            } catch (InterruptedException e) {
                continue;
            }
        }
    }

    public final synchronized void release() {
        if (mServer != null) {
            try {
                mServer.close();
            } catch (IOException e) {
                // ignore the exception
            }
        }
    }
}
